package com.lykj.job.core.thread;

import com.lykj.common.constant.CommonConstant;
import com.lykj.job.core.biz.AdminBiz;
import com.lykj.job.core.biz.model.RegistryParam;
import com.lykj.job.core.biz.model.ReturnT;
import com.lykj.job.core.enums.RegistryConfig;
import com.lykj.job.core.executor.LykjJobExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.TimeUnit;

/**
 * Created by lykj on 17/3/2.
 */
public class ExecutorRegistryThread {
	private static Logger logger = LoggerFactory.getLogger(ExecutorRegistryThread.class);

	private static ExecutorRegistryThread instance = new ExecutorRegistryThread();

	public static ExecutorRegistryThread getInstance() {
		return instance;
	}

	private Thread registryThread;
	// 是否开启任务线程 开启执行器注册
	private volatile boolean toStop = CommonConstant.JOB_TO_STOP;

	public void start(final String appname, final String address) {

		// valid
		if (appname == null || appname.trim().length() == 0) {
			logger.warn(">>>>>>>>>>> lykj-job, executor registry config fail, appname is null.");
			return;
		}
		if (LykjJobExecutor.getAdminBizList() == null) {
			logger.warn(">>>>>>>>>>> lykj-job, executor registry config fail, adminAddresses is null.");
			return;
		}

		registryThread = new Thread(new Runnable() {
			@Override
			public void run() {
				// registry
				while (!toStop) {
					try {
						RegistryParam registryParam = new RegistryParam(RegistryConfig.RegistType.EXECUTOR.name(), appname, address);
						for (AdminBiz adminBiz : LykjJobExecutor.getAdminBizList()) {
							try {
								ReturnT<String> registryResult = adminBiz.registry(registryParam);
								if (registryResult != null && ReturnT.SUCCESS_CODE == registryResult.getCode()) {
									registryResult = ReturnT.SUCCESS;
									logger.debug(">>>>>>>>>>> lykj-job registry success, registryParam:{}, registryResult:{}", new Object[]{registryParam, registryResult});
									break;
								} else {
									logger.info(">>>>>>>>>>> lykj-job registry fail, registryParam:{}, registryResult:{}", new Object[]{registryParam, registryResult});
								}
							} catch (Exception e) {
								logger.info(">>>>>>>>>>> lykj-job registry error, registryParam:{}", registryParam, e);
							}
						}
					} catch (Exception e) {
						if (!toStop) {
							logger.error(e.getMessage(), e);
						}
					}

					try {
						if (!toStop) {
							TimeUnit.SECONDS.sleep(RegistryConfig.BEAT_TIMEOUT);
						}
					} catch (InterruptedException e) {
						if (!toStop) {
							logger.warn(">>>>>>>>>>> lykj-job, executor registry thread interrupted, error msg:{}", e.getMessage());
						}
					}

					// registry remove
					try {
						RegistryParam registryParam = new RegistryParam(RegistryConfig.RegistType.EXECUTOR.name(), appname, address);
						for (AdminBiz adminBiz : LykjJobExecutor.getAdminBizList()) {
							try {
								ReturnT<String> registryResult = adminBiz.registryRemove(registryParam);
								if (registryResult != null && ReturnT.SUCCESS_CODE == registryResult.getCode()) {
									registryResult = ReturnT.SUCCESS;
									logger.info(">>>>>>>>>>> lykj-job registry-remove success, registryParam:{}, registryResult:{}", new Object[]{registryParam, registryResult});
									break;
								} else {
									logger.info(">>>>>>>>>>> lykj-job registry-remove fail, registryParam:{}, registryResult:{}", new Object[]{registryParam, registryResult});
								}
							} catch (Exception e) {
								if (!toStop) {
									logger.info(">>>>>>>>>>> lykj-job registry-remove error, registryParam:{}", registryParam, e);
								}
							}
						}
					} catch (Exception e) {
						if (!toStop) {
							logger.error(e.getMessage(), e);
						}
					}
					logger.info(">>>>>>>>>>> lykj-job, executor registry thread destroy.");
				}
			}
		});
		registryThread.setDaemon(true);
		registryThread.setName("lykj-job, executor ExecutorRegistryThread");
		registryThread.start();
	}

	public void toStop() {
		toStop = true;

		// interrupt and wait
		if (registryThread != null) {
			registryThread.interrupt();
			try {
				registryThread.join();
			} catch (InterruptedException e) {
				logger.error(e.getMessage(), e);
			}
		}

	}

}
